package net.wicp.tams.common.micro;

import java.util.Map;
import java.util.Properties;

import javax.annotation.PostConstruct;
import javax.servlet.Servlet;
import javax.sql.DataSource;

import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.SqlSessionTemplate;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.web.servlet.ServletRegistrationBean;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.scheduling.quartz.SchedulerFactoryBean;

import lombok.extern.slf4j.Slf4j;
import net.wicp.tams.common.Conf;
import net.wicp.tams.common.apiext.StringUtil;
import net.wicp.tams.common.connector.executor.IBusiManager;
import net.wicp.tams.common.connector.executor.IConfigManager;
import net.wicp.tams.common.connector.executor.busi.KeyConfigManager;
import net.wicp.tams.common.connector.executor.impl.CommonService;
import net.wicp.tams.common.jdbc.DruidAssit;
import net.wicp.tams.common.micro.connector.ConnectorServlet;
import net.wicp.tams.common.micro.connector.SpringBusiManager;
import net.wicp.tams.common.micro.quartz.IScheduleJobStore;

@Slf4j
@Configuration
@Order(Ordered.HIGHEST_PRECEDENCE)
public class ConfigInit {
	// 为了非spring程序调用spring程序
	public static ApplicationContext context;
	@Autowired
	private SpringBootAssit springBootAssit;

	@PostConstruct
	private void init() {
		Properties inputpamas = new Properties();
		Properties tpProps = Conf.copyProperties();
		Map<String, String> allMap = springBootAssit.findAllProps();
		for (Object key : tpProps.keySet()) {
			String keystr = String.valueOf(key);
			if (allMap.containsKey(keystr)) {
				inputpamas.put(keystr, String.valueOf(allMap.get(keystr)));
			}
		}
		log.info("input parmas:{}", inputpamas.toString());
		Conf.overProp(inputpamas);
	}

	@Configuration
	@Order(Ordered.HIGHEST_PRECEDENCE)
	protected class InitContext implements ApplicationContextAware {
		@Override
		public void setApplicationContext(ApplicationContext arg0) throws BeansException {
			ConfigInit.context = arg0;
		}
	}

	@Configuration
	@ConditionalOnClass(CommonService.class)
	@Order(Ordered.LOWEST_PRECEDENCE)
	public class ConnectionConfig {
		@Bean
		@ConditionalOnMissingBean
		protected IConfigManager createIConfigManager() {
			IConfigManager manage = new KeyConfigManager();
			return manage;
		}

		@Bean
		protected CommonService createExecutor(ApplicationContext context, IConfigManager configManager) {
			CommonService executor = new CommonService();
			IBusiManager busi = new SpringBusiManager(context);
			executor.setBusiManager(busi);
			executor.setConfigManager(configManager);
			return executor;
		}

		@Bean
		public ConnectorServlet servlet() {
			return new ConnectorServlet();
		}

		//兼容springboot1 ,不用ServletRegistrationBean<Servlet>
		@Bean
		public ServletRegistrationBean confServlet(ConnectorServlet servlet) {
			ServletRegistrationBean registration = new ServletRegistrationBean(servlet, true,
					"/connector");
			// registration.setEnabled(true);
			// registration.addUrlMappings("/connector");// connector的默认处理器
			return registration;
		}
	}



	@Bean
	@ConditionalOnBean(value = IScheduleJobStore.class)
	public SchedulerFactoryBean quartzJob() {
		return new SchedulerFactoryBean();
	}

	@Configuration
	@ConditionalOnClass(name = "net.wicp.tams.common.jdbc.DruidAssit")
	//@ConditionalOnEnabledEndpoint("env")
	public class DruidDBConfig {
		@Bean("primaryDatasource") // 声明其为Bean实例
		@Primary // 在同样的DataSource中，首先使用被标注的DataSource
		@ConditionalOnClass(name = "net.wicp.tams.common.jdbc.DruidAssit")
		public DataSource dataSource() {
			DataSource datasource = DruidAssit.getInst().getDataSource();
			return datasource;
		}
	}

	// mybatis配置
	// @MapperScan(basePackages = "net.wicp.tams.demo.micro.common.dao",
	// sqlSessionTemplateRef = "primarySqlSessionTemplate") 有了它就不用每个接口写 @Mapper
	// 了，但它不能动态配置，放弃
	@Configuration
	@ConditionalOnClass(name = { "net.wicp.tams.common.jdbc.DruidAssit", "org.mybatis.spring.SqlSessionFactoryBean" })
	public class MybatisConfig {
		@Bean(name = "primarySqlSessionFactory")
		@Primary
		@ConditionalOnBean(name = "primaryDatasource")
		public SqlSessionFactory rdsSqlSessionFactory(
				@Qualifier("primaryDatasource") javax.sql.DataSource primaryDataSource) throws Exception {
			final SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean();
			sessionFactory.setDataSource(primaryDataSource);
			if (StringUtil.isNotNull(Conf.get("common.micro.mybatis.mapperLocations"))) {
				sessionFactory.setMapperLocations(new PathMatchingResourcePatternResolver()
						.getResources(Conf.get("common.micro.mybatis.mapperLocations")));
			}
			if (StringUtil.isNotNull(Conf.get("common.micro.mybatis.configLocation"))) {
				sessionFactory.setConfigLocation(new PathMatchingResourcePatternResolver()
						.getResource(Conf.get("common.micro.mybatis.configLocation")));
			}
			return sessionFactory.getObject();
		}

		@Bean(name = "primarySqlSessionTemplate")
		@Primary
		@ConditionalOnBean(name = "primarySqlSessionFactory")
		public SqlSessionTemplate testSqlSessionTemplate(
				@Qualifier("primarySqlSessionFactory") SqlSessionFactory sqlSessionFactory) throws Exception {
			return new SqlSessionTemplate(sqlSessionFactory);
		}

		@Primary
		@Bean(name = "primaryJdbcTemplate")
		@ConditionalOnBean(name = "primaryDatasource")
		public JdbcTemplate primaryJdbcTemplate(@Qualifier("primaryDatasource") DataSource dataSource) {
			return new JdbcTemplate(dataSource);
		}
	}
}
